/**
 * 
 */
package com.android.fxcontacts;

import java.util.ArrayList;
import java.util.List;

import android.app.ListActivity;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.provider.CallLog;
import android.provider.CallLog.Calls;
import android.provider.Contacts.Intents.Insert;
import android.provider.ContactsContract.Contacts;
import android.provider.ContactsContract.PhoneLookup;
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.telephony.PhoneNumberUtils;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.text.format.DateUtils;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

/**
 * Displays the details of a specific call log entry.
 */
public class CallDetailActivity extends ListActivity implements
		AdapterView.OnItemClickListener
{
	private static final String TAG = "CallDetail";

	// CallerInfo constant
	public static final String CALLERINFO_UNKNOWN_NUMBER = "-1";
	public static final String CALLERINFO_PRIVATE_NUMBER = "-2";
	public static final String CALLERINFO_PAYPHONE_NUMBER = "-3";

	public static final String ACTION_CALL_PRIVILEGED = "android.intent.action.CALL_PRIVILEGED";

	private TextView mCallType;
	private ImageView mCallTypeIcon;
	private TextView mCallTime;
	private TextView mCallDuration;

	private String mNumber = null;

	/* package */LayoutInflater mInflater;
	/* package */Resources mResources;

	static final String[] CALL_LOG_PROJECTION = new String[] {
			CallLog.Calls.DATE, CallLog.Calls.DURATION, CallLog.Calls.NUMBER,
			CallLog.Calls.TYPE, };

	static final int DATE_COLUMN_INDEX = 0;
	static final int DURATION_COLUMN_INDEX = 1;
	static final int NUMBER_COLUMN_INDEX = 2;
	static final int CALL_TYPE_COLUMN_INDEX = 3;

	static final String[] PHONES_PROJECTION = new String[] { PhoneLookup._ID,
			PhoneLookup.DISPLAY_NAME, PhoneLookup.TYPE, PhoneLookup.LABEL,
			PhoneLookup.NUMBER, };
	static final int COLUMN_INDEX_ID = 0;
	static final int COLUMN_INDEX_NAME = 1;
	static final int COLUMN_INDEX_TYPE = 2;
	static final int COLUMN_INDEX_LABEL = 3;
	static final int COLUMN_INDEX_NUMBER = 4;

	@Override
	protected void onCreate(Bundle icicle)
	{
		super.onCreate(icicle);

		setContentView(R.layout.call_detail);

		mInflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
		mResources = getResources();

		mCallType = (TextView) findViewById(R.id.type);
		mCallTypeIcon = (ImageView) findViewById(R.id.icon);
		mCallTime = (TextView) findViewById(R.id.time);
		mCallDuration = (TextView) findViewById(R.id.duration);

		getListView().setOnItemClickListener(this);
	}

	@Override
	public void onResume()
	{
		super.onResume();
		updateData(getIntent().getData());
	}

	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event)
	{
		switch (keyCode)
		{
		case KeyEvent.KEYCODE_CALL:
		{
			// Make sure phone isn't already busy before starting direct call
			TelephonyManager tm = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
			if (tm.getCallState() == TelephonyManager.CALL_STATE_IDLE)
			{
				Intent callIntent = new Intent(ACTION_CALL_PRIVILEGED, Uri
						.fromParts("tel", mNumber, null));
				startActivity(callIntent);
				return true;
			}
		}
		}

		return super.onKeyDown(keyCode, event);
	}

	/**
	 * Update user interface with details of given call.
	 * 
	 * @param callUri
	 *            Uri into {@link CallLog.Calls}
	 */
	private void updateData(Uri callUri)
	{
		ContentResolver resolver = getContentResolver();
		Cursor callCursor = resolver.query(callUri, CALL_LOG_PROJECTION, null,
				null, null);
		try
		{
			if (callCursor != null && callCursor.moveToFirst())
			{
				// Read call log specifics
				mNumber = callCursor.getString(NUMBER_COLUMN_INDEX);
				long date = callCursor.getLong(DATE_COLUMN_INDEX);
				long duration = callCursor.getLong(DURATION_COLUMN_INDEX);
				int callType = callCursor.getInt(CALL_TYPE_COLUMN_INDEX);

				// Pull out string in format [relative], [date]
				CharSequence dateClause = DateUtils.formatDateRange(this, date,
						date, DateUtils.FORMAT_SHOW_TIME
								| DateUtils.FORMAT_SHOW_DATE
								| DateUtils.FORMAT_SHOW_WEEKDAY
								| DateUtils.FORMAT_SHOW_YEAR);
				mCallTime.setText(dateClause);

				// Set the duration
				if (callType == Calls.MISSED_TYPE)
				{
					mCallDuration.setVisibility(View.GONE);
				} else
				{
					mCallDuration.setVisibility(View.VISIBLE);
					mCallDuration.setText(formatDuration(duration));
				}

				// Set the call type icon and caption
				String callText = null;
				switch (callType)
				{
				case Calls.INCOMING_TYPE:
					mCallTypeIcon
							.setImageResource(R.drawable.ic_call_log_header_incoming_call);
					mCallType.setText(R.string.type_incoming);
					callText = getString(R.string.callBack);
					break;

				case Calls.OUTGOING_TYPE:
					mCallTypeIcon
							.setImageResource(R.drawable.ic_call_log_header_outgoing_call);
					mCallType.setText(R.string.type_outgoing);
					callText = getString(R.string.callAgain);
					break;

				case Calls.MISSED_TYPE:
					mCallTypeIcon
							.setImageResource(R.drawable.ic_call_log_header_missed_call);
					mCallType.setText(R.string.type_missed);
					callText = getString(R.string.returnCall);
					break;
				}

				if (mNumber.equals(CALLERINFO_UNKNOWN_NUMBER)
						|| mNumber.equals(CALLERINFO_PRIVATE_NUMBER))
				{
					// List is empty, let the empty view show instead.
					TextView emptyText = (TextView) findViewById(R.id.emptyText);
					if (emptyText != null)
					{
						emptyText
								.setText(mNumber
										.equals(CALLERINFO_PRIVATE_NUMBER) ? R.string.private_num
										: R.string.unknown);
					}
				} else
				{
					// Perform a reverse-phonebook lookup to find the PERSON_ID
					String callLabel = null;
					Uri personUri = null;
					Uri phoneUri = Uri
							.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI,
									Uri.encode(mNumber));
					Cursor phonesCursor = resolver.query(phoneUri,
							PHONES_PROJECTION, null, null, null);
					try
					{
						if (phonesCursor != null && phonesCursor.moveToFirst())
						{
							long personId = phonesCursor
									.getLong(COLUMN_INDEX_ID);
							personUri = ContentUris.withAppendedId(
									Contacts.CONTENT_URI, personId);
							callText = getString(
									R.string.recentCalls_callNumber,
									phonesCursor.getString(COLUMN_INDEX_NAME));
							mNumber = PhoneNumberUtils
									.formatNumber(phonesCursor
											.getString(COLUMN_INDEX_NUMBER));
							// callLabel = Phone.getDisplayLabel(this,
							// phonesCursor.getInt(COLUMN_INDEX_TYPE),
							// phonesCursor.getString(COLUMN_INDEX_LABEL))
							// .toString();
							callLabel = Phone.getTypeLabel(this.getResources(),
									phonesCursor.getInt(COLUMN_INDEX_TYPE),
									phonesCursor.getString(COLUMN_INDEX_LABEL))
									.toString();
						} else
						{
							mNumber = PhoneNumberUtils.formatNumber(mNumber);
						}
					} finally
					{
						if (phonesCursor != null)
							phonesCursor.close();
					}

					// Build list of various available actions
					List<ViewEntry> actions = new ArrayList<ViewEntry>();

					Intent callIntent = new Intent(ACTION_CALL_PRIVILEGED, Uri
							.fromParts("tel", mNumber, null));
					ViewEntry entry = new ViewEntry(
							android.R.drawable.sym_action_call, callText,
							callIntent);
					entry.number = mNumber;
					entry.label = callLabel;
					actions.add(entry);

					Intent smsIntent = new Intent(Intent.ACTION_SENDTO, Uri
							.fromParts("sms", mNumber, null));
					actions
							.add(new ViewEntry(R.drawable.sym_action_sms,
									getString(R.string.menu_sendTextMessage),
									smsIntent));

					// Let user view contact details if they exist, otherwise
					// add option
					// to create new contact from this number.
					if (personUri != null)
					{
						Intent viewIntent = new Intent(Intent.ACTION_VIEW,
								personUri);
						actions.add(new ViewEntry(
								R.drawable.sym_action_view_contact,
								getString(R.string.menu_viewContact),
								viewIntent));
					} else
					{
						Intent createIntent = new Intent(
								Intent.ACTION_INSERT_OR_EDIT);
						createIntent.setType(Contacts.CONTENT_ITEM_TYPE);
						createIntent.putExtra(Insert.PHONE, mNumber);
						actions.add(new ViewEntry(R.drawable.sym_action_add,
								getString(R.string.recentCalls_addToContact),
								createIntent));
					}

					ViewAdapter adapter = new ViewAdapter(this, actions);
					setListAdapter(adapter);
				}
			} else
			{
				// Something went wrong reading in our primary data, so we're
				// going to
				// bail out and show error to users.
				Toast.makeText(this, R.string.toast_call_detail_error,
						Toast.LENGTH_SHORT).show();
				finish();
			}
		} finally
		{
			if (callCursor != null)
			{
				callCursor.close();
			}
		}
	}

	private String formatDuration(long elapsedSeconds)
	{
		long minutes = 0;
		long seconds = 0;

		if (elapsedSeconds >= 60)
		{
			minutes = elapsedSeconds / 60;
			elapsedSeconds -= minutes * 60;
		}
		seconds = elapsedSeconds;

		return getString(R.string.callDetailsDurationFormat, minutes, seconds);
	}

	static final class ViewEntry
	{
		public int icon = -1;
		public String text = null;
		public Intent intent = null;
		public String label = null;
		public String number = null;

		public ViewEntry(int icon, String text, Intent intent)
		{
			this.icon = icon;
			this.text = text;
			this.intent = intent;
		}
	}

	static final class ViewAdapter extends BaseAdapter
	{

		private final List<ViewEntry> mActions;

		private final LayoutInflater mInflater;

		public ViewAdapter(Context context, List<ViewEntry> actions)
		{
			mActions = actions;
			mInflater = (LayoutInflater) context
					.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
		}

		public int getCount()
		{
			return mActions.size();
		}

		public Object getItem(int position)
		{
			return mActions.get(position);
		}

		public long getItemId(int position)
		{
			return position;
		}

		public View getView(int position, View convertView, ViewGroup parent)
		{
			// Make sure we have a valid convertView to start with
			if (convertView == null)
			{
				convertView = mInflater.inflate(R.layout.call_detail_list_item,
						parent, false);
			}

			// Fill action with icon and text.
			ViewEntry entry = mActions.get(position);
			convertView.setTag(entry);

			ImageView icon = (ImageView) convertView.findViewById(R.id.icon);
			TextView text = (TextView) convertView
					.findViewById(android.R.id.text1);

			icon.setImageResource(entry.icon);
			text.setText(entry.text);

			View line2 = convertView.findViewById(R.id.line2);
			boolean numberEmpty = TextUtils.isEmpty(entry.number);
			boolean labelEmpty = TextUtils.isEmpty(entry.label) || numberEmpty;
			if (labelEmpty && numberEmpty)
			{
				line2.setVisibility(View.GONE);
			} else
			{
				line2.setVisibility(View.VISIBLE);

				TextView label = (TextView) convertView
						.findViewById(R.id.label);
				if (labelEmpty)
				{
					label.setVisibility(View.GONE);
				} else
				{
					label.setText(entry.label);
					label.setVisibility(View.VISIBLE);
				}

				TextView number = (TextView) convertView
						.findViewById(R.id.number);
				number.setText(entry.number);
			}

			return convertView;
		}
	}

	public void onItemClick(AdapterView parent, View view, int position, long id)
	{
		// Handle passing action off to correct handler.
		if (view.getTag() instanceof ViewEntry)
		{
			ViewEntry entry = (ViewEntry) view.getTag();
			if (entry.intent != null)
			{
				startActivity(entry.intent);
			}
		}
	}

	@Override
	public void startSearch(String initialQuery, boolean selectInitialQuery,
			Bundle appSearchData, boolean globalSearch)
	{
		if (globalSearch)
		{
			super.startSearch(initialQuery, selectInitialQuery, appSearchData,
					globalSearch);
		} else
		{
			ContactsSearchManager.startSearch(this, initialQuery);
		}
	}

}
